//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.ruoyi.common.utils.toolkit;

import cn.hutool.core.lang.Assert;
import com.ruoyi.tool.ExceptionUtils.CollectionUtils;
import com.ruoyi.tool.ExceptionUtils.ExceptionUtils;
import net.bytebuddy.utility.privilege.SetAccessibleAction;
import org.springframework.util.ClassUtils;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public final class ReflectionKit {
    private static final Map<Class<?>, List<Field>> CLASS_FIELD_CACHE = new ConcurrentHashMap();
    /**
     * @deprecated
     */
    @Deprecated
    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new IdentityHashMap(8);
    private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_TO_WRAPPER_MAP = new IdentityHashMap(8);

    public ReflectionKit() {
    }

    public static Object getFieldValue(Object entity, String fieldName) {
        Class<?> cls = entity.getClass();
        Map<String, Field> fieldMaps = getFieldMap(cls);

        try {
            Field field = (Field) fieldMaps.get(fieldName);
            Assert.notNull(field, "Error: NoSuchField in %s for %s.  Cause:", new Object[]{cls.getSimpleName(), fieldName});
            field.setAccessible(true);
            return field.get(entity);
        } catch (ReflectiveOperationException var5) {
            ReflectiveOperationException e = var5;
            throw ExceptionUtils.mpe("Error: Cannot read field in %s.  Cause:", e, new Object[]{cls.getSimpleName()});
        }
    }

    public static Class<?> getSuperClassGenericType(final Class<?> clazz, final Class<?> genericIfc, final int index) {
        Class<?>[] typeArguments = GenericTypeUtils.resolveTypeArguments(ClassUtils.getUserClass(clazz), genericIfc);
        return null == typeArguments ? null : typeArguments[index];
    }

    public static Map<String, Field> getFieldMap(Class<?> clazz) {
        List<Field> fieldList = getFieldList(clazz);
        return CollectionUtils.isNotEmpty(fieldList) ? (Map) fieldList.stream().collect(Collectors.toMap(Field::getName, Function.identity())) : Collections.emptyMap();
    }

    public static List<Field> getFieldList(Class<?> clazz) {
        return Objects.isNull(clazz) ? Collections.emptyList() : (List) CollectionUtils.computeIfAbsent(CLASS_FIELD_CACHE, clazz, (k) -> {
            Field[] fields = k.getDeclaredFields();
            List<Field> superFields = new ArrayList();

            for (Class<?> currentClass = k.getSuperclass(); currentClass != null; currentClass = currentClass.getSuperclass()) {
                Field[] declaredFields = currentClass.getDeclaredFields();
                Collections.addAll(superFields, declaredFields);
            }

            Map<String, Field> fieldMap = excludeOverrideSuperField(fields, superFields);
            return (List) fieldMap.values().stream().filter((f) -> {
                return !Modifier.isStatic(f.getModifiers());
            }).filter((f) -> {
                return !Modifier.isTransient(f.getModifiers());
            }).collect(Collectors.toList());
        });
    }

    public static Map<String, Field> excludeOverrideSuperField(Field[] fields, List<Field> superFieldList) {
        Map<String, Field> fieldMap = (Map) Stream.of(fields).collect(Collectors.toMap(Field::getName, Function.identity(), (u, v) -> {
            throw new IllegalStateException(String.format("Duplicate key %s", u));
        }, LinkedHashMap::new));
        superFieldList.stream().filter((field) -> {
            return !fieldMap.containsKey(field.getName());
        }).forEach((f) -> {
            Field var10000 = (Field) fieldMap.put(f.getName(), f);
        });
        return fieldMap;
    }

    /**
     * @deprecated
     */
    @Deprecated
    public static boolean isPrimitiveOrWrapper(Class<?> clazz) {
        Assert.notNull(clazz, "Class must not be null", new Object[0]);
        return clazz.isPrimitive() || PRIMITIVE_WRAPPER_TYPE_MAP.containsKey(clazz);
    }

    public static Class<?> resolvePrimitiveIfNecessary(Class<?> clazz) {
        return clazz.isPrimitive() && clazz != Void.TYPE ? (Class) PRIMITIVE_TYPE_TO_WRAPPER_MAP.get(clazz) : clazz;
    }

    public static <T extends AccessibleObject> T setAccessible(T object) {
        return (T) AccessController.doPrivileged(new SetAccessibleAction(object));
    }

    static {
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Boolean.class, Boolean.TYPE);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Byte.class, Byte.TYPE);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Character.class, Character.TYPE);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Double.class, Double.TYPE);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Float.class, Float.TYPE);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Integer.class, Integer.TYPE);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Long.class, Long.TYPE);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Short.class, Short.TYPE);
        Iterator var0 = PRIMITIVE_WRAPPER_TYPE_MAP.entrySet().iterator();

        while (var0.hasNext()) {
            Map.Entry<Class<?>, Class<?>> entry = (Map.Entry) var0.next();
            PRIMITIVE_TYPE_TO_WRAPPER_MAP.put(entry.getValue(), entry.getKey());
        }

    }
}
